package com.xyrl.project.common.log.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xyrl.common.base.exception.XyrlException;
import com.xyrl.common.util.RedisUtil;
import com.xyrl.common.util.StringUtil;
import com.xyrl.project.common.constant.XyrlConstant;
import com.xyrl.project.common.domian.MsgCodeVo;
import com.xyrl.project.common.log.dao.SmsSendLogMapper;
import com.xyrl.project.common.log.entity.SmsSendLog;
import com.xyrl.project.common.log.service.SmsSendLogService;
import com.xyrl.third.aliyun.constant.AliYunConstant;
import com.xyrl.third.aliyun.exception.AliYunException;
import com.xyrl.third.aliyun.service.MsgService;
import com.xyrl.third.aliyun.vo.AliYunResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;


/**
 * @author 徐恩源
 * @version 1.0
 * @className SmsSendLogServiceImpl.java
 * @company 重庆星纭融链科技公司
 * @date 2019-12-30 16:48:43
 * @Description 短信发送日志serviceImpl
 */
@Service
public class SmsSendLogServiceImpl extends ServiceImpl<SmsSendLogMapper, SmsSendLog> implements SmsSendLogService {
    @Autowired
    private MsgService msgService;

    /**
     * 发送短信验证码间隔时间
     */
    @Value("${msg.send.interval.time:60}")
    private Long sendMsgCodeInterval;
    /**
     * 验证码 过期时间
     */
    @Value("${msg.code.expire.time:1800}")
    private Long msgCodeExpireTime;
    @Value("${aliyun.msg.signName}")
    private String signName;


    @Override
    public void sendSmsVerificationCode(String mobile, String templateId, String smsType) throws XyrlException {
        sendSmsVerificationCode(mobile, templateId, smsType, null);
    }

    @Override
    public void sendSmsVerificationCode(String mobile, String templateId, String smsType, Long userId) throws XyrlException {
        try {
            String cacheKey = StringUtil.concat(smsType, ":", mobile);
            //生成随机验证码
            String validCode = StringUtil.randomNumberCode(4);
            Map<String, String> params = new HashMap<>();
            params.put("code", validCode);
            //发送短信
            sendSms(mobile, templateId, signName, smsType, params, userId);
            //判断短信发送装态
            MsgCodeVo vo = new MsgCodeVo(mobile, validCode);
            //缓存短信发送信息
            RedisUtil.setData(StringUtil.concat(XyrlConstant.ALIYUN_SMS_VALID_TERM, cacheKey), vo, msgCodeExpireTime, TimeUnit.SECONDS);
        } catch (XyrlException e) {
            throw e;
        } catch (Exception e) {
            throw new XyrlException(e.getMessage());
        }
    }

    /**
     * 发送短信（有短信发送频率限制）
     *
     * @param mobile     接收短信手机号
     * @param templateId 短信模版id
     * @param signName   签名
     * @param smsType    短信类型
     * @param params     参数
     * @param userId     用户id（营业员）
     * @author zhongp
     * @date 2020-01-03 14:54:29
     */
    private void sendSms(String mobile, String templateId, String signName, String smsType, Map<String, String> params, Long userId) throws XyrlException {
        SmsSendLog smsSendLog = new SmsSendLog();
        smsSendLog.setSalesmanId(userId);
        smsSendLog.setMobile(mobile);
        smsSendLog.setType(smsType);
        smsSendLog.setParams(JSON.toJSONString(params));
        smsSendLog.setTemplateId(templateId);
        smsSendLog.setCreateTime(new Date());
        try {
            String cacheKey = StringUtil.concat(smsType, ":", mobile);
            String sendKey = StringUtil.concat(XyrlConstant.ALIYUN_SMS_INTERVAL_TERM, cacheKey);
            //判断是否在发送频率时间间隔内
            if (RedisUtil.hasKey(sendKey)) {
                throw new XyrlException("发送过于频繁，请稍后再试");
            }
            Map<String, String> map = new HashMap<>();
            //接收短信号码
            map.put("PhoneNumbers", mobile);
            //短信模版id
            map.put("TemplateCode", templateId);
            //短信签名
            map.put("SignName", signName);
            //短信内容包函数的参数值
            map.put("TemplateParam", JSON.toJSONString(params));
            AliYunResponse response = msgService.sendMsg(map);
            smsSendLog.setResponse(JSON.toJSONString(response));
            //判断短信发送装态
            if (!AliYunConstant.ALI_YUN_RTN_SUCCESS.equalsIgnoreCase(response.getCode())) {
                throw new XyrlException(response.getMessage());
            }
            //缓存短信发送信息
            RedisUtil.setData(sendKey, mobile, sendMsgCodeInterval, TimeUnit.SECONDS);
        } catch (XyrlException e) {
            smsSendLog.setResponse(e.getMessage());
            throw e;
        } catch (AliYunException e) {
            smsSendLog.setResponse(e.getMessage());
            throw new XyrlException(e.getMessage());
        } catch (Exception e) {
            smsSendLog.setResponse(e.getMessage());
            throw new XyrlException(e.getMessage());
        } finally {
            this.baseMapper.insert(smsSendLog);
        }
    }

}
